package com.lichongbing.lyoggl.apple;

import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.lichongbing.lyoggl.config.CacheConfig;
import com.lichongbing.lyoggl.config.ConstConfig;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lichongbing
 * @version 1.0.0
 * @createdate 2022/8/18 21:08
 * @description: TODO
 */
@Service
public class AppleServe {
    @Autowired
    private Cache<String, String> cache;
    @Autowired
    private RestTemplate restTemplate;
    @Value("appleIDRevokeAud")
    private static String appleIdRevokeAud;
    @Value("${appleIDValidateURL}")
    private String appleIdValidateURL;
    @Value("${redirectURI}")
    private String redirectURI;
    @Value("${kid}")
    private String kid;
    @Value("${iss}")
    private String iss;
    @Value("${privateKey}")
    private String privateKey;
    @Value("${expSeconds}")
    private String expSeconds;
    @Value("${ISS_FIELD}")
    private String ISS_FIELD;
    @Value("${PRIVATEKEY_ALGORITHM_EC}")
    private String PRIVATEKEY_ALGORITHM_EC;
    @Value("${clientID}")
    private static String clientID;
    @Value("teamID")
    private static String teamID;
    @Value("keyID")
    private static String keyID;
    @Value("keyValue")
    private static String keyValue;


    /**
     * refresh_token -> rb17934d3409e4fe7864bf1f7be4b162c.0.svvr.eplErTX6EV6ur-HR_I4SWw
     * access_token -> ab7f8c1eb2db54c2b9f52a8ad797396c0.0.svvr.M8YvLINnCmYlBUhXbrXd4g
     * 根据authorizationCode授权码来获取refreshToken
     * @param authorizationCode
     * @return
     */
    public String generateToken(String authorizationCode) throws Exception {
        String refreshToken = null;
        try {
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            map.add("client_id", ConstConfig.CLIENT_ID);
            map.add("client_secret", generateClientSecret());
            map.add("grant_type", "authorization_code");
            map.add("code", authorizationCode);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
            JSONObject json = restTemplate.postForEntity(appleIdValidateURL, request, JSONObject.class).getBody();
            refreshToken = json.getString("refresh_token");
        } catch (HttpClientErrorException e) {
            //WZHException是我自定义的异常类
            throw new Exception(e.getMessage());
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return refreshToken;
    }

    /**
     * 生成客户端密钥
     * @return
     * @throws Exception
     */
    public static String generateClientSecret() throws Exception {
        Map<String, Object> header = new HashMap<>();
        //P8文件下载得到的Key ID
        header.put("kid", ConstConfig.KEY_ID);
        //SHA256
        header.put("alg", SignatureAlgorithm.ES256.getValue());
        Map<String, Object> claims = new HashMap<>();
        long now = System.currentTimeMillis() / 1000;
        claims.put("iss", ConstConfig.TEAM_ID);
        claims.put("iat", now);
        // 最长半年，单位秒
        claims.put("exp", now + 648000);
        claims.put("aud", ConstConfig.REVOKE_AUD);
        claims.put("sub", ConstConfig.CLIENT_ID);
        //P8文件下载得到的Key Value
        String  privatekeyValue = "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg8kBsSgsjGF2eLsP2aIAmM9zOs/h2BrjotbeU9bvxKeugCgYIKoZIzj0DAQehRANCAARyGmG7AeBTKtud0/VZZ8SUieA+CMIODKvIuAHAcQkUJL2jJhnCCW87cqUBIQFisdNX8EKCMA7JZUR+BxyaHjN+";
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privatekeyValue));
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        return Jwts.builder().setHeader(header).setClaims(claims).signWith(SignatureAlgorithm.ES256, privateKey).compact();
    }
}
